#include "Widget.h"
#include "ui_Widget.h"
#include<QSerialPort>
#include<QSerialPortInfo>
#include<QDebug>
#include <QMessageBox>
#include <QFileDialog>
#include<QDateTime>
#include <QTcpSocket>
#include <QNetworkInterface>
#include <QtEndian>

#include<QPrinter>
#include<QPrintDialog>
#include<QPrintPreviewDialog>
#include<QFileDialog>
#include<QFileInfo>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //打印


    //串口
    //加入串口控制对象
    serialPort=new QSerialPort(this);

    //定时发送系统时间
    QTimer *getSysTime=new QTimer(this);
    connect(getSysTime,SIGNAL(timeout()),this,SLOT(time_refresh()));
    getSysTime->start(10);

    //串口参数初始化
    writeCntTotal=0;
    readCntTotal=0;
    serialStatus=false;

    //串口控件初始化
    ui->btn_send->setEnabled(false);
    ui->checkBox_senddingshi->setEnabled(false);
    ui->checkBox_huanhang->setEnabled(false);
    ui->lineEdit_dingshi->setEnabled(false);
    ui->label_sendstatus->setText("Not Open!");

    //定时发送
    timer=new QTimer(this);

    connect(serialPort,&QSerialPort::readyRead,this,&Widget::on_SerialData_readyToRead);
    connect(timer,&QTimer::timeout,this,[=](){
        on_btn_send_clicked();
    });

    ui->comboBox_botelv->setCurrentIndex(6);
    ui->comboBox_shujuwei->setCurrentIndex(3);

    //获取串口端口
    QList<QSerialPortInfo> serialList=QSerialPortInfo::availablePorts();
    for(QSerialPortInfo &serialInfo : serialList){
        qDebug() << serialInfo.portName();
        ui->comboBox_chuankou->addItem(serialInfo.portName());
    }

    //网口Tcp服务端
    //加入网口服务端控制对象
    server = new QTcpServer(this);

    connect(server,SIGNAL(newConnection()),this,SLOT(newClient_connect()));

    ui->btn_Lineout->setEnabled(false);
    ui->btn_stoplisten->setEnabled(false);
    ui->btn_sendser->setEnabled(false);

    //获取IP地址
    QList<QHostAddress> adresses=QNetworkInterface::allAddresses();
    for(QHostAddress &adr : adresses){
        if(adr.protocol()==QAbstractSocket::IPv4Protocol){
            ui->comboBox_fuwuquIP->addItem(adr.toString());
        }
    }

    //网口Tcp客户端
    client = new QTcpSocket(this);

    connect(client,SIGNAL(readyRead()),this,SLOT(Data_From_Server()));

    ui->btn_stopuser->setEnabled(false);
    ui->btn_senduser->setEnabled(false);

    //网口Udp服务端
    Qudpserver=new QUdpSocket(this);

    //网口Udp客户端
    Qudpuser=new QUdpSocket(this);
    Qudpuser->bind(QHostAddress::Any,8888);//绑定端口
    connect(Qudpuser,&QUdpSocket::readyRead,this,&Widget::on_readyreadUdpuser);

    //网口Udp服务端
    Qudpserver=new QUdpSocket(this);
    Qudpserver->bind(QHostAddress::Any,8080);
    connect(Qudpserver,&QUdpSocket::readyRead,this,&Widget::on_readyreadUdpserver);

}

Widget::~Widget()
{
    delete ui;
}


//串口
//打开串口
void Widget::on_btncloseoropen_clicked()
{
    if(!serialStatus){
        //选择端口号、配置波特率、数据位、停止位、流控、校验位、打开串口
        serialPort->setPortName(ui->comboBox_chuankou->currentText());
        serialPort->setBaudRate(ui->comboBox_botelv->currentText().toInt());
        serialPort->setDataBits(QSerialPort::DataBits(ui->comboBox_shujuwei->currentText().toUInt()));
        serialPort->setStopBits(QSerialPort::StopBits(ui->comboBox_tingzhiwei->currentText().toUInt()));
        if(ui->comboBox_liukong->currentText()=="None"){
            serialPort->setFlowControl(QSerialPort::NoFlowControl);}
        switch(ui->comboBox_jiaoyanwei->currentIndex()){
        case 0:
            serialPort->setParity(QSerialPort::NoParity);
            break;
        case 1:
            serialPort->setParity(QSerialPort::EvenParity);
            break;
        case 2:
            serialPort->setParity(QSerialPort::MarkParity);
            break;
        case 3:
            serialPort->setParity(QSerialPort::OddParity);
            break;
        case 4:
            serialPort->setParity(QSerialPort::SpaceParity);
            break;
        default:
            break;
        }
        if(serialPort->open(QIODevice::ReadWrite)){
            qDebug() << "SerialPort open success";
            ui->comboBox_botelv->setEnabled(false);
            ui->comboBox_chuankou->setEnabled(false);
            ui->comboBox_jiaoyanwei->setEnabled(false);
            ui->comboBox_shujuwei->setEnabled(false);
            ui->comboBox_tingzhiwei->setEnabled(false);
            ui->comboBox_liukong->setEnabled(false);
            ui->btncloseoropen->setText("关闭串口");
            ui->btn_send->setEnabled(true);
            ui->checkBox_senddingshi->setEnabled(true);
            ui->lineEdit_fasong->setEnabled(true);
            ui->checkBox_huanhang->setEnabled(true);
            ui->lineEdit_dingshi->setEnabled(true);
            serialStatus=true;
            ui->label_sendstatus->setText("Opened!");
        }else{
            QMessageBox msgBox;
            msgBox.setWindowTitle("提示");
            msgBox.setText("打开失败，串口可能被占用或者已拔出！");
            msgBox.exec();
        }
    }else{
        serialPort->close();
        qDebug() << "SerialPort closed";
        ui->btncloseoropen->setText("打开串口");
        ui->comboBox_botelv->setEnabled(true);
        ui->comboBox_chuankou->setEnabled(true);
        ui->comboBox_jiaoyanwei->setEnabled(true);
        ui->comboBox_shujuwei->setEnabled(true);
        ui->comboBox_tingzhiwei->setEnabled(true);
        ui->comboBox_liukong->setEnabled(true);
        ui->btn_send->setEnabled(false);
        ui->checkBox_senddingshi->setEnabled(false);
        ui->checkBox_senddingshi->setCheckState(Qt::Unchecked);
        serialStatus=false;
        ui->checkBox_huanhang->setEnabled(false);
        ui->lineEdit_dingshi->setEnabled(false);
        ui->label_sendstatus->setText("Closed!");
        timer->stop();
    }
}
//串口发送
void Widget::on_btn_send_clicked()
{
    int writeCnt=0;
    //读取内容
    std::string data = ui->lineEdit_fasong->text().toStdString();
    writeCnt=serialPort->write(data.c_str(), data.length());

    if(writeCnt==-1){
        ui->label_sendstatus->setText("Send Error!");
    }else{
        writeCntTotal+=writeCnt;
        qDebug() << "Send OK!" << QString::fromStdString(data);
        ui->label_sendstatus->setText("Send OK!");
        ui->label_sendnum->setText("Sent:"+ QString::number(writeCntTotal));
        if(data != sendBak.toStdString()){
            ui->textEditRecord->insertPlainText(QString::fromStdString(data).append("\r\n"));
            sendBak=QString(QString::fromStdString(data));
        }
    }
}
//串口接收
void Widget::on_SerialData_readyToRead()
{
    QString revMessage = serialPort->readAll();
    if(!revMessage.isEmpty()){
        if(ui->checkBox_huanhang->isChecked()){
            revMessage.append("\r\n");
        }
        qDebug() << "getMessage" << revMessage;
        //解析串口数据
        double longitude, latitude;
        if (parseSerialData(revMessage, longitude, latitude)) {
            // 显示数据
            displayData(longitude, latitude);
            // 通过网络发送给客户端
            QByteArray networkData = packNetworkData(longitude, latitude);
            qDebug() << networkData;
            //Tcp客户端发送给服务端
            if(ui->btn_connectuser->isChecked()){
                client->write(networkData);
                ui->textEdit_revuser->append("客户端："+networkData);}
            //Udp客户端发送给服务端
            if(ui->lineEdit_UdpserIP==nullptr || ui->lineEdit_Udpsercom==nullptr){
                return;
            }
            QString serverIP=ui->lineEdit_UdpserIP->text();
            quint16 serverPort=ui->lineEdit_Udpsercom->text().toInt();
            Qudpuser->writeDatagram(networkData,QHostAddress(serverIP),serverPort);
        }


        ui->textEditRev->append(revMessage);

        readCntTotal+=revMessage.size();
        ui->label_revnum->setText("Receive:"+ QString::number(readCntTotal));
        ui->textEditRev->moveCursor(QTextCursor::End);
        ui->textEditRev->ensureCursorVisible();
    }
}
//串口定时发送
void Widget::on_checkBox_senddingshi_clicked(bool checked)
{
    qDebug() << "dingshifasong" << checked;
    if(checked){
        ui->lineEdit_dingshi->setEnabled(false);
        ui->lineEdit_fasong->setEnabled(false);
        timer->start(ui->lineEdit_dingshi->text().toInt());
    }else{
        timer->stop();
        ui->lineEdit_dingshi->setEnabled(true);
        ui->lineEdit_fasong->setEnabled(true);
    }
}
//串口清空接收
void Widget::on_btnrevclear_clicked()
{
    ui->textEditRev->setText("");
}
//串口保存接收
void Widget::on_btnrevsave_clicked()
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"),
                                                    "D/QTproject/serialData.txt",
                                                    tr("txt (*.txt)"));
    if(!fileName.isEmpty()){
        QFile file(fileName);
        if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
            return;

        QTextStream out(&file);
        out << ui->textEditRev->toPlainText();
        file.close();
    }

}
//串口更新时间
void Widget::time_refresh()
{
    getSysTim();
    ui->label_time->setText(myTime);
}
//串口获取系统时间
void Widget::getSysTim()
{
    QDateTime currentTime=QDateTime::currentDateTime();

    QDate date=currentTime.date();
    int year=date.year();
    int month=date.month();
    int day=date.day();

    QTime time=currentTime.time();
    int hour=time.hour();
    int minute=time.minute();
    int second=time.second();

    myTime=QString("%1-%2-%3 %4:%5:%6")
                 .arg(year,2,10,QChar('0'))
                 .arg(month,2,10,QChar('0'))
                 .arg(day,2,10,QChar('0'))
                 .arg(hour,2,10,QChar('0'))
                 .arg(minute,2,10,QChar('0'))
                 .arg(second,2,10,QChar('0'));
}
//串口隐藏历史
void Widget::on_btmhideTab_clicked(bool checked)
{
    if(checked){
        ui->btmhideTab->setText("显示历史");
        ui->groupBoxRecord->hide();
    }else{
        ui->btmhideTab->setText("隐藏历史");
        ui->groupBoxRecord->show();
    }
}

// 解析串口数据
bool Widget::parseSerialData(const QString &data, double &longitude, double &latitude)
{
    if (!data.startsWith("$AE,") || !data.endsWith("\r\n")) {
        return false;
    }

    // 去除首尾标记
    QString content = data.mid(4, data.length()-6);
    QStringList parts = content.split(",");

    if (parts.size() != 2) {
        return false;
    }

    // 转换为数值
    bool ok1, ok2;
    longitude = parts[0].toDouble(&ok1);
    latitude = parts[1].toDouble(&ok2);

    return ok1 && ok2;
}
//格式化串口数据
QString Widget::formatSerialData(double longitude, double latitude)
{
    return QString("$AE,%1,%2\r\n")
    .arg(longitude, 0, 'f', 5)
        .arg(latitude, 0, 'f', 5);
}
//解析网络数据
bool Widget::parseNetworkData(const QByteArray &data, double &longitude, double &latitude)
{
    if(data.size()!=sizeof(DataPacket)){
        return false;
    }
    DataPacket *packet=(DataPacket*)data.data();
    if(qFromBigEndian(packet->identifier)!=(qint16)(0XAABB)){
        return false;
    }
    longitude=qFromBigEndian(packet->longitude);
    latitude = qFromBigEndian(packet->latitude);
    return true;
}
//组包网络数据
QByteArray Widget::packNetworkData(double longitude, double latitude)
{
    DataPacket packet;
    packet.identifier=qToBigEndian((qint16)0xAABB);
    packet.latitude=qToBigEndian(latitude);
    packet.longitude=qToBigEndian(longitude);
    packet.reserved=0;
    return QByteArray((char*)&packet, sizeof(DataPacket));
}
//显示经纬度数据
void Widget::displayData(double longitude, double latitude)
{
    ui->textEdit_jingweidu->append(QString("经度：%1\n纬度：%2").arg(longitude, 0, 'f', 5).arg(latitude, 0, 'f', 5));

}
//保存经纬度数据以文本
void Widget::on_pushButton_clicked()
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"),
                                                    "D/QTproject/jingweiduData.txt",
                                                    tr("txt (*.txt)"));
    if(!fileName.isEmpty()){
        QFile file(fileName);
        if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
            return;
        QTextStream out(&file);
        QString line=QString("%1").arg(ui->textEdit_jingweidu->toPlainText());
        out << line;
        file.close();
    }
}


//网口Tcp服务端
//连接
void Widget::newClient_connect()
{
    if(server->hasPendingConnections()){
        QTcpSocket *connection=server->nextPendingConnection();
        ui->textEditrevser->insertPlainText("连接成功！\n客户端端口："+connection->peerAddress().toString()+
                                            "\n端口号:"+QString::number(connection->peerPort())+"\n");

        connect(connection,SIGNAL(readyRead()),this,SLOT(on_readyRead_handler()));
        connect(connection,SIGNAL(disconnected()),this,SLOT(serdisconnect()));
        ui->btn_sendser->setEnabled(true);
    }
}
//接收
void Widget::on_readyRead_handler()
{
    QTcpSocket *revread=qobject_cast<QTcpSocket *>(sender());
    QByteArray revData=revread->readAll();
    ui->textEditrevser->append("客户端："+revData);
    double longitude, latitude;
    if(parseNetworkData(revData, longitude, latitude)){
        //显示经纬度
        displayData(longitude, latitude);
        //格式化串口数据
        QString serialData=formatSerialData(longitude, latitude);
        //通过串口发送
        serialPort->write(serialData.toUtf8());
    }
}
//未连接检测
void Widget::serdisconnect()
{
    QTcpSocket *revread=qobject_cast<QTcpSocket *>(sender());
    ui->textEditrevser->insertPlainText("客户端断开！");
    revread->deleteLater();
}
//开始监听
void Widget::on_btn_Listen_clicked()
{
    int port=ui->lineEdit_duankouhao->text().toInt();
    if(!server->listen(QHostAddress(ui->comboBox_fuwuquIP->currentText()),port)){
        qDebug() << "ListenError!";
        QMessageBox msgBox;
        msgBox.setWindowTitle("监听失败");
        msgBox.setText("端口号被占用！");
        msgBox.exec();
        return;
    }
    ui->btn_Listen->setEnabled(false);
    ui->btn_Lineout->setEnabled(true);
    ui->btn_stoplisten->setEnabled(true);
}
//停止监听
void Widget::on_btn_stoplisten_clicked()
{
    QList<QTcpSocket*> clients = server->findChildren<QTcpSocket*>();
    for (QList<QTcpSocket*>::iterator it = clients.begin(); it != clients.end(); ++it) {
        (*it)->close();
    }
    server->close();
    ui->btn_Listen->setEnabled(true);
    ui->btn_Lineout->setEnabled(false);
    ui->btn_stoplisten->setEnabled(false);
    ui->btn_sendser->setEnabled(true);
}
//发送
void Widget::on_btn_sendser_clicked()
{
    QList<QTcpSocket*> clients = server->findChildren<QTcpSocket*>();
    for (QList<QTcpSocket*>::iterator it = clients.begin(); it != clients.end(); ++it) {
        (*it)->write(ui->textEditsendser->toPlainText().toStdString().c_str());
        ui->textEditrevser->append("服务端："+ui->textEditsendser->toPlainText().toUtf8());
    }
}
//断开连接
void Widget::on_btn_Lineout_clicked()
{
    on_btn_stoplisten_clicked();
    delete server;
    this->close();
}

//网口Tcp客户端
//连接
void Widget::on_btn_connectuser_clicked()
{
    client->connectToHost(ui->lineEdit_userIP->text(),ui->lineEdit_userport->text().toInt());
    connect(client,SIGNAL(connected()),this,SLOT(on_connected()));
}
//接收
void Widget::Data_From_Server()
{
    ui->textEdit_revuser->append("服务端："+client->readAll());
}
//发送
void Widget::on_btn_senduser_clicked()
{
    client->write(ui->textEdit_senduser->toPlainText().toUtf8());
    ui->textEdit_revuser->append("客户端："+ui->textEdit_senduser->toPlainText().toUtf8());
}
//断开
void Widget::on_btn_stopuser_clicked()
{
    client->close();
    ui->textEdit_revuser->append("断开连接！");
    ui->btn_connectuser->setEnabled(true);
    ui->lineEdit_userIP->setEnabled(true);
    ui->lineEdit_userport->setEnabled(true);
    ui->btn_stopuser->setEnabled(false);
    ui->btn_senduser->setEnabled(false);
}
//连接成功
void Widget::on_connected()
{
    ui->textEdit_revuser->append("连接成功！");
    ui->btn_connectuser->setEnabled(false);
    ui->lineEdit_userIP->setEnabled(false);
    ui->lineEdit_userport->setEnabled(false);
    ui->btn_stopuser->setEnabled(true);
    ui->btn_senduser->setEnabled(true);
}

//Udp客户端
//接收
void Widget::on_readyreadUdpuser()
{
    //接收并显示
    char buf[1024]={0};
    double longitude, latitude;
    QHostAddress serverIP;
    quint16 serverPort;
    qint64 len=Qudpuser->readDatagram(buf,sizeof(buf),&serverIP,&serverPort);
    if(len>0){
        ui->textEdit_Udpuserrev->append(buf);
    }

}
//发送
void Widget::on_btn_Udpusersend_clicked()
{
    //读取编辑区内容，写入
    if(ui->lineEdit_UdpserIP==nullptr || ui->lineEdit_Udpsercom==nullptr || ui->textEdit_Udpusersend==nullptr){
        return;
    }
    QString serverIP=ui->lineEdit_UdpserIP->text();
    quint16 serverPort=ui->lineEdit_Udpsercom->text().toInt();
    QString str=ui->textEdit_Udpusersend->toPlainText();
    Qudpuser->writeDatagram(str.toUtf8(),QHostAddress(serverIP),serverPort);
}
//关闭
void Widget::on_btn_Udpuserclose_clicked()
{
    Qudpuser->close();
}

//Udp服务端
//接收
void Widget::on_readyreadUdpserver()
{
    while (Qudpserver->hasPendingDatagrams()) {
        QByteArray datagram;
        QHostAddress sender;
        quint16 senderPort;

        datagram.resize(Qudpserver->pendingDatagramSize());
        Qudpserver->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);

        ui->textEdit_Udpserrev->append(datagram.data());

        // 解析网络数据
        double longitude, latitude;
        if (parseNetworkData(datagram, longitude, latitude)) {
            // 显示数据
            displayData(longitude, latitude);

            // 通过串口发送
            if (serialStatus) {
                QString serialData = formatSerialData(longitude, latitude);
                serialPort->write(serialData.toUtf8());
            }
        }
    }
}
//发送
void Widget::on_btn_Udpsersend_clicked()
{
    if(ui->lineEdit_UdpuserIP==nullptr || ui->lineEdit_Udpusercom==nullptr || ui->textEdit_Udpsersend==nullptr){
        return;
    }
    QString userIP=ui->lineEdit_UdpuserIP->text();
    quint16 userPort=ui->lineEdit_Udpusercom->text().toInt();
    QString str=ui->textEdit_Udpsersend->toPlainText();
    Qudpserver->writeDatagram(str.toUtf8(),QHostAddress(userIP),userPort);
}
//关闭
void Widget::on_btn_Udpserclose_clicked()
{
    Qudpserver->close();
}




void Widget::on_pushButton_2_clicked()
{
    QPrinter printer;
    QPrintPreviewDialog preview(&printer,this);
    connect(&preview,&QPrintPreviewDialog::paintRequested,this,&Widget::preview);
    preview.exec();
}

void Widget::preview(QPrinter *printer)
{
    ui->textEdit_jingweidu->print(printer);
}

